<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
<!--    
                                              88           88              
      ,d                                      88           88              
      88                                      88           88              
    MM88MMM  88       88  88,dPYba,,adPYba,   88,dPPYba,   88  8b,dPPYba,  
      88     88       88  88P'   "88"    "8a  88P'    "8a  88  88P'   "Y8  
      88     88       88  88      88      88  88       d8  88  88          
      88,    "8a,   ,a88  88      88      88  88b,   ,a8"  88  88        888
      "Y888   `"YbbdP'Y8  88      88      88  8Y"Ybbd8"'   88  88        888
      
-->

    
    	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    	<meta name="viewport" content="width = 710">
    	
    	    	
    	<link rel="icon" href="http://www.tumblr.com/images/favicon.gif" type="image/gif">
    	<link rel="apple-touch-icon" href="http://www.tumblr.com/images/apple_touch_icon.png">
    	
    	<script type="text/javascript" language="javascript">var tinyMCE;</script>
    	
    	<script type="text/javascript" language="javascript" src="api_files/prototype.js"></script>

    	<script type="text/javascript" language="javascript" src="api_files/effects.js"></script>

    	<script type="text/javascript" language="javascript" src="api_files/application.js"></script>

    	<script type="text/javascript" language="javascript" src="api_files/tumblelog.js"></script>

    	    	
    	    	
    	<link rel="stylesheet" type="text/css" href="api_files/global.css">
    	
    	    	    <link rel="stylesheet" type="text/css" href="api_files/docs.css">
    	    	
    	    	
    	    	
    	<title>API | Tumblr</title>
    </head><body id="main_doc_page" onclick="click_body();">
    
        <div id="container">
            <div id="header">
                <a href="http://www.tumblr.com/dashboard"><img src="api_files/logo.png" alt="Tumblr" id="logo"></a>
                <div id="nav">
                                            <a href="http://www.tumblr.com/explore">Explore</a>
                        <a href="http://www.tumblr.com/goodies">Goodies</a>                        <a href="http://www.tumblr.com/preferences">Preferences</a>
                        <a href="http://www.tumblr.com/help">Help</a>
                        <a href="http://www.tumblr.com/logout">Log out</a>
                                    </div>
                <div id="new_post_notice_container"></div>
                <div id="content_tab">
                                            <a href="http://www.tumblr.com/dashboard" style="font-size: 90%;">Go to my Dashboard →</a>
                                        
                    <img src="api_files/content_tab_left_2.png" id="content_tab_left" alt="">
                </div>
            </div>
            <div id="content_container">
                <div id="content">
                    

<h1>API</h1>

<p>The Tumblr API is implemented over standard HTTP requests. This
allows Tumblr to be integrated with just about any application that can
connect to the web.</p>

<h2>Contents</h2>
<ul>
    <li>
        <a href="#api_read">/api/read</a>: Reading posts as XML or JSON
        <ul>
            <li><a href="#authenticated_read">Authenticated read</a>: Including private posts in <code>/api/read</code></li>
        </ul>
    </li>
    <li>
        <a href="#api_write">/api/write</a>: Creating posts
        <ul>
            <li><a href="#editing_posts">Editing posts</a></li>
            <li><a href="#deleting_posts">Deleting posts</a></li>
        </ul>
    </li>
    <li><a href="#authenticate">/api/authenticate</a>: Validating credentials and getting account information</li>
    <li><a href="#iphone">iPhone access</a></li>
    <li><a href="#login_system">Tumblr's login system</a></li>
</ul>

<h2 id="api_read">/api/read</h2>

<p>Reading Tumblr data is easy: just fetch the page at <code>http://<span class="example">(you)</span>.tumblr.com/api/read</code> and you'll get a structured XML version of your content in this format:</p>

<pre>&lt;tumblr version="1.0"&gt;
    &lt;tumblelog ... &gt;
        ...
        &lt;feeds&gt;
            &lt;feed ... /&gt;
            &lt;feed ... /&gt;
            ...
        &lt;/feeds&gt;
    &lt;/tumblelog&gt;
    &lt;posts&gt;
        &lt;post type="regular" ... &gt;
            &lt;regular-title&gt;...&lt;/regular-title&gt;
            &lt;regular-body&gt;...&lt;/regular-body&gt;
        &lt;/post&gt;
        &lt;post type="link" ... &gt;
            &lt;link-text&gt;...&lt;/link-text&gt;
            &lt;link-url&gt;...&lt;/link-url&gt;
        &lt;/post&gt;
        &lt;post type="quote" ... &gt;
            &lt;quote-text&gt;...&lt;/quote-text&gt;
            &lt;quote-source&gt;...&lt;/quote-source&gt;
        &lt;/post&gt;
        &lt;post type="photo" ... &gt;
            &lt;photo-caption&gt;...&lt;/photo-caption&gt;
            &lt;photo-url max-width="500"&gt;...&lt;/photo-url&gt;
            &lt;photo-url max-width="400"&gt;...&lt;/photo-url&gt;
            ...
        &lt;/post&gt;
        &lt;post type="conversation" ... &gt;
            &lt;conversation-title&gt;...&lt;/conversation-title&gt;
            &lt;conversation-text&gt;...&lt;/conversation-text&gt;
            &lt;conversation&gt;
                &lt;line name="..." label="..."&gt;...&lt;/line&gt;
                &lt;line name="..." label="..."&gt;...&lt;/line&gt;
                ...
            &lt;/conversation&gt;
        &lt;/post&gt;
        &lt;post type="video" ... &gt;
            &lt;video-caption&gt;...&lt;/video-caption&gt;
            &lt;video-source&gt;...&lt;/video-source&gt;
            &lt;video-player&gt;...&lt;/video-player&gt;
        &lt;/post&gt;
        &lt;post type="audio" ... &gt;
            &lt;audio-caption&gt;...&lt;/audio-caption&gt;
            &lt;audio-player&gt;...&lt;/audio-player&gt;
        &lt;/post&gt;
        ...
    &lt;/posts&gt;
&lt;/tumblr&gt;
</pre>

<p>The most recent 20 posts are included by default. You may pass these optional GET parameters:</p>
    
<ul>
    <li><code>start</code> - The post offset to start from.  The default is 0.</li>

    <li><code>num</code> - The number of posts to return.  The default is 20, and the maximum is 50.</li>
    
    <li><code>type</code> - The type of posts to return.  If unspecified or empty, all types of posts are returned.  Must be one of <code>regular</code>, <code>quote</code>, <code>photo</code>, <code>link</code>, <code>conversation</code>, <code>video</code>, or <code>audio</code>.</li>
    
    <li><code>id</code> - A specific post ID to return.  Use instead of <code>start</code>, <code>num</code>, or <code>type</code>.</li>

    <li><code>filter</code> - Alternate filter to run on the text content. Allowed values:
    <ul>
        <li><code>text</code> - Plain text only. No HTML.</li>
        <li><code>none</code> - No post-processing. Output exactly what the author entered. (Note: Some authors write in <a href="http://daringfireball.net/projects/markdown/">Markdown</a>, which will not be converted to HTML when this option is used.)</li>
    </ul>
</li></ul>
    
<p>For detailed example feeds, see the live Read API on <a href="http://marco.tumblr.com/api/read" rel="nofollow">Marco's Log</a> or <a href="http://demo.tumblr.com/api/read" rel="nofollow">the demo tumblelog</a>.  A browser that pretty-prints XML, such as Firefox, is recommended.</p>



<h3>JSON output</h3>

<p>By using <code>/api/read/json</code> instead of <code>/api/read</code> when calling the Read API, the output will be sent as <a href="http://json.org/">JSON</a> assigned to a Javascript variable named <code>tumblr_api_read</code>. All regular Read API parameters are accepted, plus:</p>

<ul>

    <li><code>callback</code> - A function name to call with the JSON object as its only parameter.  When set, the function will be called instead of the <code>tumblr_api_read</code> variable being set.</li>
</ul>

<p>Example:</p>

<pre>&lt;script type="text/javascript" src="http://<b>(you)</b>.tumblr.com/api/read/json"&gt;&lt;/script&gt;

&lt;script type="text/javascript"&gt;
    // The variable "tumblr_api_read" is now set.
    document.write(
        '&lt;a href="' + tumblr_api_read[1][0]['@url'] + 
        '"&gt;Most recent Tumblr post&lt;/a&gt;'
    );
&lt;/script&gt;</pre>


<p>To view a human-readable map of the array's structure for easy reference, pass <code>debug=1</code> as a GET parameter.  The output will be like that of PHP's <a href="http://www.php.net/manual/en/function.print-r.php">print_r()</a> function.</p>


<h3 id="authenticated_read">Authenticated read</h3>
<p>
    To include private posts in <code>/api/read</code>, use a POST request to 
    <code>/api/read</code> and include the <code>email</code> and <code>password</code> 
    parameters (see <code>/api/write</code> below) from an account authorized to 
    view the tumblelog's Dashboard.
</p>
<p>
    Private posts are indicated in the resulting XML with the extra <code>private="true"</code> attribute
    on their <code>&lt;post&gt;</code> nodes.
</p>


<h2 id="api_write">/api/write</h2>

<p>The Write API is a very simple HTTP interface.  To create a post, send a POST request to <code>http://www.tumblr.com/api/write</code> with the following parameters:</p>

<ul>
    <li><code>email</code> - Your account's email address.</li>

    <li><code>password</code> - Your account's password.</li>

    <li><code>type</code> - The post type.</li>

    <li><i>(content parameters)</i> - These vary by post type.</li>

    <li><code>generator</code>
(optional) - A short description of the application making the request
for tracking and statistics, such as "John's Widget 1.0". Must be 64 or
fewer characters.</li>

    <li><code>date</code> (optional) - The
post date, if different from now, in the tumblelog's timezone. Most
unambiguous formats are accepted, such as '2007-12-01 14:50:02'. Dates
may not be in the future.</li>

    <li><code>private</code>
(optional) - 1 or 0. Whether the post is private. Private posts only
appear in the Dashboard or with authenticated links, and do not appear
on the tumblelog's main page.</li>

    <li><code>tags</code> (optional) - Comma-separated list of post tags.  You may optionally enclose tags in double-quotes.</li>

    <li><code>format</code> (optional) - <code>html</code> or <code>markdown</code>.</li>

    <li>
        <code>group</code> (optional) - Post this to a group instead of your tumblelog. Value types:
        <ol>
            <li>Domain, e.g. <code>mygroup.tumblr.com</code> (for public groups only)</li>
            <li>Group ID number, e.g. <code>1495028</code>.  Found with the Dashboard URL for that group, e.g.  <code>www.tumblr.com/group/1495028</code>.</li>
        </ol>
    </li>
</ul>

<h3>Post types</h3>

<p>These are the valid values for the <code>type</code> parameter, with the associated content parameters that each type supports:</p>

<ul>
    <li>
        <code>regular</code> - Requires at least one:
        <ul>
            <li><code>title</code></li>
            <li><code>body</code> (HTML allowed)</li>
        </ul>
    </li>

    <li>
        <code>photo</code> - Requires either <code>source</code> or <code>data</code>, but not both.  If both are specified, <code>source</code> is used.
        <ul>
            <li><code>source</code> - The URL of the photo to copy.  This must be a web-accessible URL, not a local file or intranet location.</li>
            
            <li><code>data</code> - An image file.  See <b>File uploads</b> below.</li>
            
            <li><code>caption</code> (optional, HTML allowed)</li>
            
            <li><code>click-through-url</code> (optional)</li>
        </ul>
    </li>
    
    <li>
        <code>quote</code>
        <ul>
            <li><code>quote</code></li>
            <li><code>source</code> (optional, HTML allowed)</li>
        </ul>
    </li>
    
    <li>
        <code>link</code>
        <ul>
            <li><code>name</code> (optional)</li>
            <li><code>url</code></li>
            <li><code>description</code> (optional, HTML allowed)</li>
        </ul>
    </li>
    
    <li>
        <code>conversation</code>
        <ul>
            <li><code>title</code> (optional)</li>
            <li><code>conversation</code></li>
        </ul>
    </li>
    <li>
        <code>video</code> - Requires either <code>embed</code> or <code>data</code>, but not both.
        <ul>
            <li><code>embed</code> - Either the complete HTML code to embed the video, or the URL of a YouTube video page.</li>

            <li><code>data</code> - A video file for a <a href="http://www.tumblr.com/vimeo">Vimeo upload</a>.  See <b>File uploads</b> below.</li>

            <li><code>title</code> (optional) - Only applies to Vimeo uploads.</li>

            <li><code>caption</code> (optional, HTML allowed)</li>
        </ul>
    </li>
    <li>
        <code>audio</code>
        <ul>
            <li><code>data</code> - An audio file. Must be MP3 or AIFF format. See <b>File uploads</b> below.</li>
            <li><code>caption</code> (optional, HTML allowed)</li>
        </ul>
    </li>
</ul>


<h3>File uploads</h3>

<p>File uploads can be done in a <code>data</code> parameter where specified above.  You may use either of the common encoding methods:</p>

<ul>
    <li>
        <code>multipart/form-data</code> method, like a file upload box in a web form.  Maximum size:
        <ul>
            <li>50 MB for videos</li>
            <li>10 MB for photos</li>
            <li>10 MB for audio</li>
        </ul>
        This is recommended since there's much less overhead.
    </li>
    <li>
Normal POST method, in which the file's entire binary contents are
URL-encoded like any other POST variable. Maximum size: <ul>
            <li>5 MB for videos</li>
            <li>5 MB for photos</li>
            <li>5 MB for audio</li>
        </ul>
    </li>
</ul>

<h3>Return values</h3>

<p>We return standard HTTP status codes for each request, plus a plaintext response.</p>
<ul>
    <li><code>201 Created</code> - Success!  The newly created post's ID is returned.</li>

    <li><code>403 Forbidden</code> - Your email address or password were incorrect.</li>

    <li><code>400 Bad Request</code> - There was at least one error while trying to save your post.  Errors are sent in plain text, one per line.</li>
</ul>


<h3>Sample PHP code</h3>

<pre>&lt;?php

<b>// Authorization info</b>
$tumblr_email    = 'info@davidville.com';
$tumblr_password = 'secret';

<b>// Data for new record</b>
$post_type  = 'regular';
$post_title = 'The post title';
$post_body  = 'This is the body of the post.';

<b>// Prepare POST request</b>
$request_data = http_build_query(
    array(
        'email'     =&gt; $tumblr_email,
        'password'  =&gt; $tumblr_password,
        'type'      =&gt; $post_type,
        'title'     =&gt; $post_title,
        'body'      =&gt; $post_body,
        'generator' =&gt; 'API example'
    )
);

<b>// Send the POST request (with cURL)</b>
$c = curl_init('http://www.tumblr.com/api/write');
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, $request_data);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($c);
$status = curl_getinfo($c, CURLINFO_HTTP_CODE);
curl_close($c);

<b>// Check for success</b>
if ($status == 201) {
    echo "Success! The new post ID is $result.\n";
} else if ($status == 403) {
    echo 'Bad email or password';
} else {
    echo "Error: $result\n";
}

?&gt;</pre>

<p>If you have trouble, please ensure that you are properly encoding
the POST parameters. If you have any other questions, please pass them
along to <a href="mailto:support@tumblr.com">Tumblr Support</a>.</p>

<h3 id="editing_posts">Editing posts</h3>
<p>
    To edit a post, create the <code>/api/write</code> request as described above,
    and pass an additional POST parameter:
</p>
<ul>
    <li><code>post-id</code> - The integer ID of the post you wish to edit.</li>
</ul>
<p>
    Pass all other parameters normally as you would with <code>/api/write</code>,
    specifying their new values, with the following exceptions:
</p>
<ul>
    <li><code>type</code>, <code>private</code>, <code>format</code> - These are ignored and can be omitted. These values cannot be changed after post creation.</li>
    <li><code>tags</code>, <code>generator</code>, <code>date</code> - These are optional. If specified, the new values will override the previous values. If omitted, the values are not changed.</li>
</ul>

<h3 id="deleting_posts">Deleting posts</h3>
<p>
    To edit a post, create the authenticated <code>/api/write</code> request as described above,
    but POST to <code>http://www.tumblr.com/api/delete</code> instead, and pass an additional POST parameter:
</p>
<ul>
    <li><code>post-id</code> - The integer ID of the post you wish to delete.</li>
</ul>
<p>
    All content-related parameters will be ignored and can be omitted.
    Only the authentication parameters and <code>post-id</code> are required.
</p>


<h2 id="authenticate">/api/authenticate</h2>
<p>
    Send a POST request to <code>http://www.tumblr.com/api/authenticate</code>
    with only the <code>email</code> and <code>password</code> parameters to
    validate credentials and get account information, such as user limits
    and tumblelogs.
</p>
<p>
    The output is XML. The root <code class="inline">&lt;tumblr&gt;</code> 
    element contains one child <code class="inline">&lt;user&gt;</code> node,
    plus one child <code class="inline">&lt;tumblelog&gt;</code> 
    element per tumblelog membership (including the user's default tumblelog).
</p>
<p>
    Attributes on <code class="inline">&lt;user&gt;</code>:
</p>
<ul>
    <li>
        <code class="inline">can-upload-audio</code>:
        "<code>1</code>" if the user can currently upload an MP3 audio file.
    </li>
    <li>
        <code class="inline">can-upload-aiff</code>:
        "<code>1</code>" if the user can currently upload an AIFF audio file.
    </li>
    <li>
        <code class="inline">can-upload-video</code>:
        "<code>1</code>" if the user can currently upload video.
        Requires the user to be logged into Vimeo through Tumblr.
    </li>
    <li>
        <code class="inline">max-video-bytes-uploaded</code>:
        Indicates the maximum number of bytes for the user's next video upload.
        Requires the user to be logged into Vimeo through Tumblr.
    </li>
</ul>
<p>
    Attributes on <code class="inline">&lt;tumblelog&gt;</code>:
</p>
<ul>
    <li>
        <code class="inline">title</code>
    </li>
    <li>
        <code class="inline">type</code>:
        <code class="inline">public</code> or
        <code class="inline">private</code>
    </li>
    <li>
        <code class="inline">private-id</code> (private tumblelogs only): 
        The ID number for private tumblelogs. Use this value for the
        <code class="inline">group</code> parameter on 
        <code class="inline">/api/write</code>.
    </li>
    <li>
        <code class="inline">name</code> (public tumblelogs only)
    </li>
    <li>
        <code class="inline">url</code> (public tumblelogs only)
    </li>
    <li>
        <code class="inline">avatar-url</code> (public tumblelogs only)
    </li>
    <li>
        <code class="inline">is-primary</code>:
        <code class="inline">yes</code> if this is the user's primary
        tumblelog
    </li>
</ul>

<h3>Deprecated</h3>
<p>
    The following values of <code>action</code> are deprecated and may be removed in the future.
</p>
<ul>
    <li><code>list-tumblelogs</code></li>
    <li><code>check-vimeo</code></li>
    <li><code>check-audio</code></li>
</ul>
<p>
    Their functionality is now included in <code class="inline">/api/authenticate</code>.
</p>

<h2 id="iphone">iPhone</h2>

<p>For iPhone apps that want to display a user's Dashboard, Tumblr offers an iPhone-optimized view at <a href="http://www.tumblr.com/iphone">http://www.tumblr.com/iphone</a>.</p>

<p>
    To avoid making the user log into Tumblr separately if you already have their credentials, 
    you can send an HTTP POST to <code class="inline">http://www.tumblr.com/login</code>
    (see <a href="#login_system">Tumblr's login system</a>)
    with these form-encoded parameters:
</p>

<ul>
    <li><code class="inline">email</code></li>
    <li><code class="inline">password</code></li>
    <li><code class="inline">redirect_to</code>: the <b>relative</b> destination URL to open after a successful login</li>
</ul>

<p>Example Cocoa code:</p>

<pre style="font-size: 11px;">NSString *email           = @"example@email.com";
NSString *password        = @"password";
NSString *destination_url = @"/iphone";

NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
    initWithURL:[NSURL URLWithString:@"http://www.tumblr.com/login"]
];
[request setHTTPMethod:@"POST"];
NSString *request_body = [NSString 
    stringWithFormat:@"email=%@&amp;password=%@&amp;redirect_to=%@",
    [email           stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
    [password        stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
    [destination_url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
];
[request setHTTPBody:[request_body dataUsingEncoding:NSUTF8StringEncoding]];
/* Load the request here with an NDA-covered iPhone component
   that can view the web.
*/
[request release];</pre>


<h2 id="login_system">Tumblr's login system</h2>
<p>
    Most applications for creating, editing, and reading post data will not need
    to interact with Tumblr's standard browser-based login system at
    <code>http://www.tumblr.com/login</code>.
</p>
<p>
    If your application uses only <code>/api/read</code> and/or <code>/api/write</code>,
    you never need to worry about cookies or login limits.
</p>
<p>
    If your application submits credentials to 
    <code>http://www.tumblr.com/login</code>, you will be issued a login cookie.
    Please keep in mind:
</p>
<ul>
    <li>
        Login cookies can expire or be invalidated outside of your application.
        They cannot be guaranteed or checked.
        In most cases, using an invalid login cookie on a page requiring a login
        will result in an HTTP redirect to <code>http://www.tumblr.com/login</code>.
    </li>
    <li>
        Users are only issued a limited number of login cookies before
        the oldest issued cookies are invalidated.
        Therefore, please do not consume unnecessary login cookies, especially
        if you do not retain them between requests. This will result in the user
        being frequently logged out of their normal browser-based logins.
    </li>
    <li>
        If your app sends a POST login to <code>http://www.tumblr.com/login</code> 
        but it supplies a valid login cookie, a duplicate will <b>not</b> be issued.
        This is the recommended practice for showing a Dashboard page in an embedded
        browser, such as the <a href="#iphone">iPhone example</a>, 
        because it won't consume unnecessary login tickets for
        the user but it will always result in a valid login (with correct credentials).
    </li>
</ul>
<p>
    Please do not use the <code>http://www.tumblr.com/login</code> system if your
    desired functionality can be accomplished with 
    <code>/api/read</code> or <code>/api/write</code>.
</p>
<p>
    Use of the <code>http://www.tumblr.com/login</code> system is unsupported and
    subject to change without notice.
</p>
                </div>
                
                <div id="footer">
                    <strong>© Tumblr, Inc.</strong>
                    <a href="http://www.tumblr.com/help">Help</a>
                    <a href="http://staff.tumblr.com/">What's New</a>
                    <a href="http://www.tumblr.com/docs/developers">Developers</a>
                    <a href="http://www.tumblr.com/content_policy">Content Policy</a>
                    <a href="http://www.tumblr.com/terms_of_service">Terms of Service</a>
                    <a href="http://www.tumblr.com/privacy_policy">Privacy Policy</a>
                </div>
            </div>
        </div>
        
        <script src="api_files/urchin.js" type="text/javascript">
        </script>
        <script type="text/javascript">
            _uacct = "UA-97144-8";
            urchinTracker();
        </script>
    </body></html>